package com.mediatek.factorymode.touchscreen2;


import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import com.mediatek.factorymode.FactoryMode;
import com.mediatek.factorymode.R;


import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AbsoluteLayout;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class LineTest extends Activity {
	static final String TAG = "LineTest";
	
	static final int EDGE_GAP = 150;
	static final int BLOCK_WIDTH = 180;
	static final int RADIUS_2 = (EDGE_GAP)* (EDGE_GAP);
	static final float MAX_VELOCITY = 80;
	
	static final int LEFT_TOP    = 0;
	static final int RIGHT_TOP   = 1;
	static final int RIGHT_BOTTOM = 2;
	static final int LEFT_BOTTOM = 3;
	
	private View mLineView;
	static int mStartPoint = -1;
	static float mLine_K;
	
	private boolean[] state_referenceLine = {false, false};
	
	private ArrayList<PT> mPoints = new ArrayList<PT>();
	private Paint mPaint;
	private Paint mCornerPaint;
	private Paint mTargetPaint;
	private int mScreenWidth;
	private int mScreenHeigh;
	private float mGradient;
	private float mPoint2Line;
	
	private Toast mToast;
	
	private VelocityTracker mVelocity;

	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE); 
        //getWindow().addFlags(WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED);
      	setContentView(R.layout.touchscreen_line);
      	
      	mLineView = new LineView(this);
      	RelativeLayout.LayoutParams param  = new RelativeLayout.LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
      	addContentView(mLineView, param);
      	
      	initView();
    }
	
	private void initView() {
		WindowManager dpy = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
        mScreenWidth = dpy.getDefaultDisplay().getWidth();
        mScreenHeigh = dpy.getDefaultDisplay().getHeight();
        mGradient = (float)mScreenHeigh / mScreenWidth;
        Log.v(TAG, "initView: mGradient = " + mGradient);
        
        mPoint2Line = (float) (EDGE_GAP / Math.sqrt(1 + mGradient * mGradient));
        Log.v(TAG, "initView: mPoint2Line = " + mPoint2Line);
        
        mLine_K = (float) Math.sqrt(mGradient * mGradient + 1);
		
		mPaint = new Paint();
		mPaint.setAntiAlias(true);
		
		mCornerPaint = new Paint();
		mCornerPaint.setAntiAlias(true);
		mCornerPaint.setColor(Color.YELLOW);
		mCornerPaint.setStyle(Paint.Style.STROKE);
		mCornerPaint.setStrokeWidth(3);
		
		mTargetPaint = new Paint();
		mTargetPaint.setAntiAlias(true);
		mTargetPaint.setColor(Color.GREEN);
		mTargetPaint.setStyle(Paint.Style.STROKE);
		mTargetPaint.setStrokeWidth(1);
		
		mToast = Toast.makeText(this, getString(R.string.tp_line_hint), Toast.LENGTH_LONG);
		mToast.show();
	}
    
	@Override
	protected void onDestroy() {
		//getWindow().clearFlags(WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED);
		super.onDestroy();
	}
	
    private void goback(int flag) {
		// TODO Auto-generated method stub
		Intent intent=new Intent();  
	    intent.setClass(LineTest.this, FactoryMode.class);  
	    setResult(flag,intent);
	    finish();
	}
	
	@Override
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_BACK:
			return true;
		}
		return super.onKeyUp(keyCode, event);
    }
    
    public class LineView extends View {

		public LineView(Context context) {
			super(context);
		}
    	
		@Override
		protected void onDraw(Canvas canvas) {
			/* Draw diagonal line */
			if(state_referenceLine[0]) {
				mPaint.setColor(Color.GREEN);
				mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
				mPaint.setStrokeWidth(BLOCK_WIDTH);
				canvas.drawLine(0, 0, mScreenWidth, mScreenHeigh, mPaint);
			} else {
				mPaint.setColor(Color.RED);
				mPaint.setStyle(Paint.Style.STROKE);
				mPaint.setStrokeWidth(3);
				canvas.drawLine(0, EDGE_GAP, mScreenWidth - EDGE_GAP, mScreenHeigh, mPaint);
				canvas.drawLine(EDGE_GAP, 0, mScreenWidth, mScreenHeigh - EDGE_GAP, mPaint);
			}
			
			if(state_referenceLine[1]) {
				mPaint.setColor(Color.GREEN);
				mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
				mPaint.setStrokeWidth(BLOCK_WIDTH);
				canvas.drawLine(0, mScreenHeigh, mScreenWidth, 0, mPaint);
			} else {
				mPaint.setColor(Color.RED);
				mPaint.setStyle(Paint.Style.STROKE);
				mPaint.setStrokeWidth(3);
				canvas.drawLine(0, mScreenHeigh - EDGE_GAP, mScreenWidth - EDGE_GAP, 0, mPaint);
				canvas.drawLine(EDGE_GAP, mScreenHeigh, mScreenWidth, EDGE_GAP, mPaint);
			}
			
			/* Draw circle */
			if(!state_referenceLine[0]) {
				canvas.drawCircle(0, 0, EDGE_GAP, mCornerPaint);
				canvas.drawCircle(mScreenWidth, mScreenHeigh, EDGE_GAP , mCornerPaint);
			}
			
			if(!state_referenceLine[1]) {
				canvas.drawCircle(mScreenWidth, 0, EDGE_GAP, mCornerPaint);
				canvas.drawCircle(0, mScreenHeigh, EDGE_GAP, mCornerPaint);
			}
			
			if(mPoints != null && mPoints.size() > 0) {
				int size = mPoints.size();
				float lastX = 0, lastY = 0;
				
				for(int i = 0; i < size; i++) {
					PT n = mPoints.get(i);
					
					if(i > 0) {
						canvas.drawLine(lastX, lastY, n.x, n.y, mTargetPaint);
						canvas.drawPoint(lastX, lastY, mTargetPaint);
					}
					
					lastX = n.x;
					lastY = n.y;
				}
			}
		}
		
		public boolean onTouchEvent(MotionEvent event) {
			float x = event.getX();
			float y = event.getY();
			
			switch(event.getAction()) {
			case MotionEvent.ACTION_DOWN:
				if(mToast != null) {
					mToast.cancel();
				}

				if(checkStartPoint(x, y)) {
					clear();
					mVelocity = VelocityTracker.obtain();
					if(mPoints != null) {
						mPoints.add(new PT(x, y));
					}
					invalidate();
				}
				break;
				
			case MotionEvent.ACTION_MOVE:
				if((mStartPoint != -1) && (isOnLine1(x, y) || isOnLine2(x, y))) {
					mVelocity.addMovement(event);
					mVelocity.computeCurrentVelocity(10);
					
					float xV = mVelocity.getXVelocity();
					float yV = mVelocity.getYVelocity();
					Log.v(TAG, "onTouchEvent: xV = " + xV);
					Log.v(TAG, "onTouchEvent: yV = " + yV);
					if((Math.abs(xV) > MAX_VELOCITY) || (Math.abs(yV) > MAX_VELOCITY)) {
						if(mToast != null) {
							//mToast.cancel();
							mToast.setText(getString(R.string.tp_slide_too_quick));
							mToast.show();
						}
						mStartPoint = -1;
						clear();
					} else {
						if(mPoints != null) {
							mPoints.add(new PT(x, y));
							
							if((int)y - mPoints.get(0).y > (mScreenHeigh - BLOCK_WIDTH)) {
								checkLastPoint(false, x, y);
							}
						}
					}
				} else {
					if(((mStartPoint == LEFT_TOP || mStartPoint == RIGHT_BOTTOM) && !state_referenceLine[0]) || 
							((mStartPoint == RIGHT_TOP || mStartPoint == LEFT_BOTTOM) && !state_referenceLine[1])) {
						if(mToast != null) {
							//mToast.cancel();
							mToast.setText(getString(R.string.tp_line_area_hint));
							mToast.show();
						}
					}
					mStartPoint = -1;
					clear();
				}
				invalidate();
				break;
				
			case MotionEvent.ACTION_UP:
				if(checkLastPoint(true, x, y)) {
					invalidate();
				}
				mStartPoint = -1;
				clear();
				break;
				
			default:
				mStartPoint = -1;
				clear();
				break;
			}
			
			return true;
		}
		
		boolean checkStartPoint(float x, float y) {
			boolean ret = false;
			mStartPoint = -1;
			
			if(x * x + y * y <= RADIUS_2) {
				mStartPoint = LEFT_TOP;
				ret = true;
			} else if((mScreenWidth - x) * (mScreenWidth - x) + y * y <= RADIUS_2) {
				mStartPoint = RIGHT_TOP;
				ret = true;
			} else if((mScreenWidth - x) * (mScreenWidth - x) + (mScreenHeigh - y) * (mScreenHeigh - y) < RADIUS_2) {
				mStartPoint = RIGHT_BOTTOM;
				ret = true;
			} else if(x * x + (mScreenHeigh - y) * (mScreenHeigh - y) <= RADIUS_2) {
				mStartPoint = LEFT_BOTTOM;
				ret = true;
			} else {
				if(!state_referenceLine[0] || !state_referenceLine[1]) {
					if(mToast != null) {
						mToast.setText(getString(R.string.tp_line_start_hint));
						mToast.show();
					}
				}
			}
			
			return ret;
		}
		
		boolean checkLastPoint(boolean isUp, float x, float y) {
			boolean ret = false;
			
			if((mStartPoint == LEFT_TOP) && ((mScreenWidth - x) * (mScreenWidth - x) + (mScreenHeigh - y) * (mScreenHeigh - y) < RADIUS_2)) {
				state_referenceLine[0] = true;
				ret = true;
			} else if((mStartPoint == RIGHT_BOTTOM) && (x * x + y * y <= RADIUS_2)) {
				state_referenceLine[0] = true;
				ret = true;
			} else if((mStartPoint == RIGHT_TOP) && (x * x + (mScreenHeigh - y) * (mScreenHeigh - y) <= RADIUS_2)) {
				state_referenceLine[1] = true;
				ret = true;
			} else if((mStartPoint == LEFT_BOTTOM) && ((mScreenWidth - x) * (mScreenWidth - x) + y * y <= RADIUS_2)) {
				state_referenceLine[1] = true;
				ret = true;
			} else {
				if(isUp && (mStartPoint != -1) && ((isOnLine1(x, y) && !state_referenceLine[0]) || (isOnLine2(x, y) && !state_referenceLine[1]))) {
					if(mToast != null) {
						mToast.setText(getString(R.string.tp_line_stop_hint));
						mToast.show();
					}
				}
			}
			
			if(state_referenceLine[0] && state_referenceLine[1]) {
				if(mToast != null) {
					mToast.setText(getString(R.string.tp_success_hint));
					mToast.show();
				}
				
				Timer timer = new Timer();
				timer.schedule(new TimerTask() {

					@Override
					public void run() {
						Intent intent = new Intent(LineTest.this, FactoryMode.class);
						setResult(1,intent);
						finish();
					}
					
				}, 1500);
			}
			
			return ret;
		}
		
		boolean isOnLine1(float x, float y) {
			boolean ret = false;
			float interval = Math.abs(mGradient * x - y) / mLine_K;
			if(interval <= mPoint2Line) {
				ret = true;
			}
			
			return ret;
		}
		
		boolean isOnLine2(float x, float y) {
			boolean ret = false;
			float interval = Math.abs(-mGradient * x - y + mScreenHeigh) / mLine_K;
			if(interval <= mPoint2Line) {
				ret = true;
			}
			
			return ret;		
		}
    }
    
    @Override
	protected void onStop() {
    	super.onStop();
    	if(mToast != null) {
			mToast.cancel();
		}
		
		if(mPoints != null) {
			mPoints.clear();
		}
    }
    
    public class PT {
		public float x;
		public float y;
		public PT(float x, float y)
		{
			this.x = x;
			this.y = y;
		}
	};
    
	void clear() {
		if(mPoints != null) {
			mPoints.clear();
		}
		
		if(mVelocity != null) {
			mVelocity.clear();
		}
	}
    
}
